package org.gdstash.formula;

import org.gdstash.db.DBItem;
import org.gdstash.file.GDParseException;
import org.gdstash.file.GDReader;
import org.gdstash.file.GDWriter;
import org.gdstash.item.GDItem;
import org.gdstash.util.FileVersionException;
import org.gdstash.util.GDConstants;
import org.gdstash.util.GDMsgFormatter;
import org.gdstash.util.GDMsgLogger;

import java.io.*;
import java.util.LinkedList;
import java.util.List;

public class GDFormulaList {
    private static final String FORMULAS_VERSION = "formulasVersion";
    private static final String NUM_ENTRIES = "numEntries";
    private static final String EXPANSION_STATUS = "expansionStatus";
    private static final String ITEM_NAME = "itemName";
    private static final String FORMULA_READ = "formulaRead";
    private File file;
    private String filename;
    private boolean hardcore;
    private boolean error;
    private byte[] beginBlock;
    private int version;
    private int numEntries;
    private byte expansionStatus;
    private byte[] endBlock;
    private List<GDFormulaEntry> entries;

    public GDFormulaList(final File file) {
        this.file = file;
        this.filename = file.getName().toUpperCase(GDConstants.LOCALE_US);
        this.hardcore = false;
        if (this.filename.endsWith(".BSH")) {
            this.hardcore = true;
        }
        if (this.filename.endsWith(".CSH")) {
            this.hardcore = true;
        }
        if (this.filename.endsWith(".GSH")) {
            this.hardcore = true;
        }
        this.entries = new LinkedList<GDFormulaEntry>();
    }

    public boolean hasErrors() {
        return this.error;
    }

    public void addBlueprints() {
        final List<DBItem> bp = DBItem.getBlueprints();
        for (final DBItem item : bp) {
            boolean found = false;
            for (final GDFormulaEntry entry : this.entries) {
                if (entry.getFormulaID().equals(item.getItemID())) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                final GDFormulaEntry entry2 = new GDFormulaEntry(item.getItemID());
                this.entries.add(entry2);
            }
        }
    }

    public List<GDItem> getItems() {
        final List<GDItem> items = new LinkedList<GDItem>();
        for (final GDFormulaEntry entry : this.entries) {
            final DBItem dbi = DBItem.get(entry.getFormulaID());
            final GDItem item = new GDItem(dbi);
            items.add(item);
        }
        return items;
    }

    public void read() {
        final String path = null;
        this.error = false;
        this.entries.clear();
        try (final InputStream reader = new BufferedInputStream(new FileInputStream(this.file))) {
            String s = null;
            final int len = 0;
            s = GDReader.readString(reader);
            if (!"begin_block".equals(s)) {
                final Object[] args = {"begin_block", path};
                final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_TAG_NOT_FOUND", args);
                throw new GDParseException(msg, 0L);
            }
            this.beginBlock = GDReader.readBytes4(reader);
            s = GDReader.readString(reader);
            if (!"formulasVersion".equals(s)) {
                final Object[] args = {"formulasVersion", path};
                final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_TAG_NOT_FOUND", args);
                throw new GDParseException(msg, 0L);
            }
            this.version = GDReader.readUInt(reader);
            if (this.version != 2 && this.version != 3) {
                throw new FileVersionException(GDMsgFormatter.getString(GDMsgFormatter.rbMsg, "ERR_UNSUPPORTED_VERSION"));
            }
            s = GDReader.readString(reader);
            if (!"numEntries".equals(s)) {
                final Object[] args = {"numEntries", path};
                final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_TAG_NOT_FOUND", args);
                throw new GDParseException(msg, 0L);
            }
            this.numEntries = GDReader.readUInt(reader);
            if (this.version >= 3) {
                s = GDReader.readString(reader);
                if (!"expansionStatus".equals(s)) {
                    final Object[] args = {"expansionStatus", path};
                    final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_TAG_NOT_FOUND", args);
                    throw new GDParseException(msg, 0L);
                }
                this.expansionStatus = GDReader.readByte(reader);
            }
            String name = null;
            int fRead = 0;
            for (int i = 0; i < this.numEntries; ++i) {
                s = GDReader.readString(reader);
                if (!"itemName".equals(s)) {
                    final Object[] args2 = {"itemName", path};
                    final String msg2 = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_TAG_NOT_FOUND", args2);
                    throw new GDParseException(msg2, 0L);
                }
                name = GDReader.readString(reader);
                s = GDReader.readString(reader);
                if (!"formulaRead".equals(s)) {
                    final Object[] args2 = {"formulaRead", path};
                    final String msg2 = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_TAG_NOT_FOUND", args2);
                    throw new GDParseException(msg2, 0L);
                }
                fRead = GDReader.readUInt(reader);
                final GDFormulaEntry entry = new GDFormulaEntry(name, fRead);
                this.entries.add(entry);
            }
            s = GDReader.readString(reader);
            if (!"end_block".equals(s)) {
                final Object[] args3 = {"end_block", path};
                final String msg3 = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_TAG_NOT_FOUND", args3);
                throw new GDParseException(msg3, 0L);
            }
            this.endBlock = GDReader.readBytes4(reader);
        } catch (FileNotFoundException ex) {
            if (path != null) {
                final Object[] args4 = {path};
                final String msg4 = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_FILE_NOT_FOUND", args4);
                GDMsgLogger.addError(msg4);
            }
            GDMsgLogger.addError(ex);
            this.error = true;
        } catch (FileVersionException ex2) {
            if (path != null) {
                final Object[] args4 = {path};
                final String msg4 = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_FILE_READ", args4);
                GDMsgLogger.addError(msg4);
            }
            GDMsgLogger.addInfo(GDMsgFormatter.getString(GDMsgFormatter.rbMsg, "INFO_UPDATE_GDSTASH"));
            GDMsgLogger.addError(ex2);
            this.error = true;
        } catch (Exception ex3) {
            if (path != null) {
                final Object[] args4 = {path};
                final String msg4 = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_FILE_READ", args4);
                GDMsgLogger.addError(msg4);
            }
            GDMsgLogger.addError(ex3);
            this.error = true;
        }
    }

    public void write() throws IOException {
        final String path = this.file.getParent() + GDConstants.FILE_SEPARATOR;
        String tname = "formulas.t";
        if (this.filename.endsWith(".BST")) {
            tname = "formulas.bt";
        }
        if (this.filename.endsWith(".BSH")) {
            tname = "formulas.bh";
        }
        if (this.filename.endsWith(".CST")) {
            tname = "formulas.ct";
        }
        if (this.filename.endsWith(".CSH")) {
            tname = "formulas.ch";
        }
        if (this.filename.endsWith(".GSH")) {
            tname = "formulas.h";
        }
        final File temp = new File(path + "temp_tmp.tmp");
        temp.createNewFile();
        final String s = null;
        try (final OutputStream writer = new BufferedOutputStream(new FileOutputStream(temp))) {
            GDWriter.writeString(writer, "begin_block");
            GDWriter.writeBytes(writer, this.beginBlock);
            GDWriter.writeString(writer, "formulasVersion");
            GDWriter.writeInt(writer, this.version);
            GDWriter.writeString(writer, "numEntries");
            GDWriter.writeInt(writer, this.entries.size());
            if (this.version == 3) {
                GDWriter.writeString(writer, "expansionStatus");
                GDWriter.writeByte(writer, this.expansionStatus);
            }
            for (final GDFormulaEntry entry : this.entries) {
                GDWriter.writeString(writer, "itemName");
                GDWriter.writeString(writer, entry.getFormulaID());
                GDWriter.writeString(writer, "formulaRead");
                GDWriter.writeInt(writer, entry.getFormulaRead());
            }
            GDWriter.writeString(writer, "end_block");
            GDWriter.writeBytes(writer, this.endBlock);
            writer.flush();
        } catch (FileNotFoundException ex) {
            if (path != null) {
                final Object[] args = {path};
                final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_FILE_NOT_FOUND", args);
                GDMsgLogger.addError(msg);
            }
            GDMsgLogger.addError(ex);
            this.error = true;
        } catch (Exception ex2) {
            if (path != null) {
                final Object[] args = {path};
                final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_FILE_READ", args);
                GDMsgLogger.addError(msg);
            }
            GDMsgLogger.addError(ex2);
            this.error = true;
        }
        if (this.error) {
            return;
        }
        File fCurr = new File(path + tname + String.format("%02d", 0));
        File fNew = null;
        for (int count = 9; count >= 0; --count) {
            fCurr = new File(path + tname + String.format("%02d", count));
            fNew = new File(path + tname + String.format("%02d", count + 1));
            if (fCurr.exists()) {
                if (count == 9) {
                    fCurr.delete();
                } else {
                    fCurr.renameTo(fNew);
                }
            }
        }
        this.file.renameTo(fCurr);
        temp.renameTo(this.file);
    }

    public void write2() throws IOException {
        final String path = this.file.getParent() + GDConstants.FILE_SEPARATOR;
        String tname = "formulas.t";
        if (this.filename.endsWith(".BST")) {
            tname = "formulas.bt";
        }
        if (this.filename.endsWith(".BSH")) {
            tname = "formulas.bh";
        }
        if (this.filename.endsWith(".CST")) {
            tname = "formulas.ct";
        }
        if (this.filename.endsWith(".CSH")) {
            tname = "formulas.ch";
        }
        if (this.filename.endsWith(".GSH")) {
            tname = "formulas.h";
        }
        File fCurr = new File(path + tname + String.format("%02d", 0));
        File fNew = null;
        for (int count = 9; count >= 0; --count) {
            fCurr = new File(path + tname + String.format("%02d", count));
            fNew = new File(path + tname + String.format("%02d", count + 1));
            if (fCurr.exists()) {
                if (count == 9) {
                    fCurr.delete();
                } else {
                    fCurr.renameTo(fNew);
                }
            }
        }
        GDWriter.copyFile(this.file, fCurr);
        try (final OutputStream writer = new BufferedOutputStream(new FileOutputStream(this.file))) {
            GDWriter.writeString(writer, "begin_block");
            GDWriter.writeBytes(writer, this.beginBlock);
            GDWriter.writeString(writer, "formulasVersion");
            GDWriter.writeInt(writer, this.version);
            GDWriter.writeString(writer, "numEntries");
            GDWriter.writeInt(writer, this.entries.size());
            if (this.version == 3) {
                GDWriter.writeString(writer, "expansionStatus");
                GDWriter.writeByte(writer, this.expansionStatus);
            }
            for (final GDFormulaEntry entry : this.entries) {
                GDWriter.writeString(writer, "itemName");
                GDWriter.writeString(writer, entry.getFormulaID());
                GDWriter.writeString(writer, "formulaRead");
                GDWriter.writeInt(writer, entry.getFormulaRead());
            }
            GDWriter.writeString(writer, "end_block");
            GDWriter.writeBytes(writer, this.endBlock);
            writer.flush();
        } catch (FileNotFoundException ex) {
            if (path != null) {
                final Object[] args = {path};
                final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_FILE_NOT_FOUND", args);
                GDMsgLogger.addError(msg);
            }
            this.error = true;
            throw ex;
        } catch (IOException ex2) {
            if (path != null) {
                final Object[] args = {path};
                final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_FILE_READ", args);
                GDMsgLogger.addError(msg);
            }
            this.error = true;
            GDWriter.copyFile(fCurr, this.file);
            throw ex2;
        }
    }
}
